/******************************************************************************
 * (c) Copyright 2010-2015, Freescale Semiconductor Inc.
 * ALL RIGHTS RESERVED.
 ***************************************************************************/
#include <appincludes.h>

/*
    This file implements the pulse out
*/

static double energy_active = 0.0;
static double energy_reactive = 0.0;

/* Default is 80ms, the PIT interval is POWER_METERING_PULSE_PIT_INTERVAL */
static uint32_t wh_valid_cnt = (POWER_METERING_PULSE_WIDTH / POWER_METERING_PULSE_PIT_INTERVAL);
static uint32_t var_valid_cnt = (POWER_METERING_PULSE_WIDTH / POWER_METERING_PULSE_PIT_INTERVAL);
static uint32_t wh_pulse_cnt = 0;
//static uint32_t varh_pulse_cnt = 0;


int32_t pulse_out_deinit(void)
{
    PIT_Disable(PIT1, CH0);

    return 0;
}

static int32_t pulse_out_set_kwh(uint32_t is_active)
{
    if (is_active)
    {
        LED_ACTIVE_HIGH();
    }
    else
    {
        LED_ACTIVE_LOW();
    }
    
    return 0;
}

//static int32_t pulse_out_set_kvarh(uint32_t is_active)
//{
//    if (is_active)
//    {
//        LED_REACTIVE_HIGH();
//    }
//    else
//    {
//        LED_REACTIVE_LOW();
//    }
//    
//    return 0;
//}



/******************** pulse/led out *********************************************/
/*
 pulse and led output 
 default pulse number is 400.

 keep 80ms for pulse out if period > 100ms
 if period < 100ms, duty = 50%

 for led output: init is low, changed to high if valid
 for pulse output: init is high, changed to low if valid
*/

/*
 period = 1000 * 3600 * 1000000 / C / P , 
 C = PULSE_ACTIVE_NUM or PULSE_REACTIVE_NUM
 unit is us.

 POWER_100MS: power value when period is 100ms.
 POWER_100MS = 1000 * 3600 * 1s / C / 100ms = 10000 * 3600 / C 
*/
/*
	toggle the pulse/led output.
*/
int32_t pulse_out_pulse_status_update(void)
{
    if (LED_ACTIVE_STATUS()==0)
    {
        wh_pulse_cnt++;
        if (wh_pulse_cnt >= wh_valid_cnt)
        {
            wh_pulse_cnt = 0;
            pulse_out_set_kwh(0);
        }
    }

//    if (LED_REACTIVE_STATUS())
//    {
//        varh_pulse_cnt++;
//        if (varh_pulse_cnt >= var_valid_cnt)
//        {
//            varh_pulse_cnt = 0;
//            pulse_out_set_kvarh(0);
//        }
//    }

    return 0;
}

int32_t pulse_out_check_power_valid_cnt(void)
{
    double cur_p_val = 0.0, cur_q_val = 0.0;

    metering_func_get_cur_p_q_total(&cur_p_val, &cur_q_val);

    /*
     Keep 80ms for pulse out if period > 100ms
     If period < 100ms, duty = 50%
    */
    if (fabs(cur_p_val) > POWER_METERING_POWER_100MS)
    {
        wh_valid_cnt = POWER_METERING_PULSE_THRES / ((int32_t)fabs(cur_p_val) * 2);
        /* PIT pulse interval is 50us. If 50us, 50% duty, that is 100us, is not enough,
           User need to change pit pulse interval */
        if (wh_valid_cnt < 1)
            return -1;
    }
    else
        wh_valid_cnt = POWER_METERING_PULSE_HOLDING_COUNT;

    if (fabs(cur_q_val) > POWER_METERING_POWER_100MS)
    {
        var_valid_cnt = POWER_METERING_PULSE_THRES / ((int32_t)fabs(cur_q_val) * 2);
        /* PIT pulse interval is 50us. If 50us, 50% duty, that is 100us, is not enough,
           User need to change pit pulse interval */
        if (var_valid_cnt < 1)
            return -1;
    }
    else
        var_valid_cnt = POWER_METERING_PULSE_HOLDING_COUNT;

    return 0;
}

int32_t pulse_out_update_period(void)
{
    double cur_p_val = 0.0, cur_q_val = 0.0;
    
    metering_func_get_cur_p_q_total(&cur_p_val, &cur_q_val);

    energy_active += cur_p_val;
    energy_reactive += cur_q_val;

    /*
      P is Wt/s, pulse_out_update_period will be called every
      POWER_METERING_PULSE_PIT_INTERVAL here.
      So, energy increases (P / ( 1000000 / POWER_METERING_PULSE_PIT_INTERVAL)) here.
      POWER_METERING_PULSE_THRES to (3600 * 1000) / POWER_METERING_PULSE_NUM.
      Magnitude two sides by  1000000 / POWER_METERING_PULSE_PIT_INTERVAL).
     */
    if (energy_active >= POWER_METERING_PULSE_THRES)
    {
        energy_active -= POWER_METERING_PULSE_THRES;
        pulse_out_set_kwh(1);
    }
    else if (energy_active <= (0 - POWER_METERING_PULSE_THRES))
    {
        energy_active += POWER_METERING_PULSE_THRES;
        pulse_out_set_kwh(1);
    }	

//    if (energy_reactive >= POWER_METERING_PULSE_THRES)
//    {
//        energy_reactive -= POWER_METERING_PULSE_THRES;
//        pulse_out_set_kvarh(1);
//    }
//    else if (energy_reactive <= (0 - POWER_METERING_PULSE_THRES))
//    {
//        energy_reactive += POWER_METERING_PULSE_THRES;
//        pulse_out_set_kvarh(1);
//    }
    
    return 0;
}

/******************************************************************************
 * End of module                                                              *
 ******************************************************************************/
